package apollo

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/apolloconfig/agollo/v4"
	"github.com/apolloconfig/agollo/v4/env/config"
	"github.com/apolloconfig/agollo/v4/storage"
	"go.uber.org/zap"
	config2 "hosptial-record/config"
	"hosptial-record/global"
	"sync"
)

type RegisterConfConfig struct {
	AppID         string `json:"app_id"`
	NamespaceName string `json:"namespace_name"`
	Secret        string `json:"secret"`
	Cluster       string `json:"cluster"`
	ConfigName    string `json:"config_name"`
}
type Registry struct {
	Host string `json:"host"`
	Port int    `json:"port"`
}

type RegistryClient interface {
	RegisterConfig(*RegisterConfConfig) error
}

func NewRegistry(host string, port int) RegistryClient {
	return Registry{
		Host: host,
		Port: port,
	}
}

func (s Registry) RegisterConfig(conf *RegisterConfConfig) error {
	c := &config.AppConfig{
		AppID:          conf.AppID,
		Cluster:        conf.Cluster,
		IP:             fmt.Sprintf("http://%s:%d", s.Host, s.Port),
		NamespaceName:  conf.NamespaceName,
		IsBackupConfig: false,
		Secret:         conf.Secret,
	}
	client, err := agollo.StartWithConfig(func() (*config.AppConfig, error) {
		return c, nil
	})
	if err != nil {
		zap.S().Errorf("Apollo注册失败：%s", err)
		panic(err)
	}
	cache := client.GetConfigCache(c.NamespaceName)
	if cache == nil {
		zap.S().Error("没用获取到配置缓存")
		panic(err)
	}
	str := client.GetConfig(c.NamespaceName).GetValue(conf.ConfigName)
	if str == "" {
		zap.S().Error("没有获取到配置，请检查Apollo配置")
		panic(errors.New("获取失败"))
	}
	// 添加监听
	listener := &CustomChangeListener{
		ConfigName: conf.ConfigName,
	}
	client.AddChangeListener(listener)
	global.ServerConfig, err = json2Config(str)
	if err != nil {
		return err
	}
	return nil
}

type CustomChangeListener struct {
	ConfigName string
	wg         sync.WaitGroup
}

// 实现监听
func (c *CustomChangeListener) OnChange(changeEvent *storage.ChangeEvent) {
	for key, value := range changeEvent.Changes {
		// 判断是否为需要的文件进行变化
		if key == c.ConfigName {
			str := value.NewValue.(string)
			var err error
			global.ServerConfig, err = json2Config(str)
			if err != nil {
				zap.S().Errorf("配置更新失败：%s", err.Error())
				panic(err)
			} else {
				zap.S().Infof("文件更新成功：%s", str)
			}
		}
	}
}

func (c *CustomChangeListener) OnNewestChange(event *storage.FullChangeEvent) {
	//write your code here
}

func json2Config(data string) (*config2.ServerConfig, error) {
	// 将json进行编码
	var serverConfig config2.ServerConfig
	if err := json.Unmarshal([]byte(data), &serverConfig); err != nil {
		zap.S().Errorf("配置编码失败：%s", err.Error())
		return nil, err
	}
	return &serverConfig, nil
}
